home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 11 / develop 11 code / The NetWork Project / Examples (Sources) / NetSim / HistogramUnit.inc < prev    next >
Encoding:
Text File  |  1992-07-15  |  7.9 KB  |  315 lines  |  [TEXT/MPS ]

  1.     USES sane;{ HistogramUnit.inc     © Copyright G. Sawitzki, 1988-1991}
  2.     {$S Histogram}
  3.  
  4. PROCEDURE initStat(VAR stat:tStatType;name:str15);
  5. BEGIN
  6.     WITH stat DO BEGIN
  7.         count:=0;
  8.         mean:=0;
  9.         ssq:=0;
  10.         min:=+Inf; max:=-inf;
  11.         id:=name;
  12.     END;
  13. END;
  14.  
  15. {Subroutine  AddStat 1.2}
  16. {  For evaluation of mean and sum of deviation squares}
  17. { this procedure executes one single iteration}
  18. { obeying a provisional mean algorithm.}
  19. { At "w" the actual value is expected,}
  20. { at "stat" mean,SSQ and number of the preceding ones}
  21. { according the statlab-convention.}
  22. { type stattyp = record}
  23. {        count : integer;}
  24. {        mean  : extended;}
  25. {        ssq   : extended}
  26. {                end;}
  27. {}
  28. {Updating history:}
  29. {1.2 added mi/max. gs.}
  30.  
  31.  
  32. PROCEDURE addstat;
  33.     {(w : extended;    var    stat : stattyp    );    }
  34. VAR
  35.     xDiff: extended;
  36. BEGIN
  37.     IF (ClassExtended(w) in [SNAN,QNAN,Infinite]) THEN  SysBreakStr('w');
  38.     WITH stat DO
  39.     BEGIN
  40.         count := count + 1;
  41.         xDiff := w - mean;
  42.         mean := mean + xDiff / count;
  43.     IF (ClassExtended(mean) in [SNAN,QNAN,Infinite]) THEN  SysBreakStr('mean');
  44.         ssq := ssq + xDiff * (w - mean);
  45.         IF w > max THEN
  46.         BEGIN
  47.             max := w;
  48.         END;
  49.         IF w < min THEN
  50.         BEGIN
  51.             min := w;
  52.         END;
  53.     END;
  54. END;
  55.  
  56. PROCEDURE addbistat;
  57.  
  58. { (x, y : extended;var xstat, ystat : tStatType;    var    xyssq : extended    ) ;   }
  59.  
  60.  
  61.     {Fuction: accumulate (x,y) into the statistics}
  62.     {Input: (x,y): new data}
  63.     {       xstat,ystat,xyssq: current statistics}
  64.     {Output:  xstat,ystat,xyssq: updated statistics}
  65.  
  66.  
  67.     {Updating by method of provisional means}
  68.     {BMDP Statistical Software, Appendix A.2}
  69.     {xyssq: sum of (x-xmean)(y-ymean)}
  70.     {no checks performed, count overflow will not be detected}
  71.  
  72. VAR
  73.     xDiff, ydiff: extended;
  74. BEGIN
  75.     {update statistics for x}
  76.     WITH xstat DO
  77.     BEGIN
  78.         count := succ(count);
  79.         xDiff := x - mean;
  80.         mean := mean + xDiff / count;
  81.         ssq := ssq + xDiff * (x - mean);
  82.     END;
  83.     {update statistics for y and cross-products}
  84.     WITH ystat DO
  85.     BEGIN
  86.         count := count + 1;
  87.         yDiff := y - mean;
  88.         mean := mean + yDiff / count;
  89.         ssq := ssq + yDiff * (y - mean);
  90.         xyssq := xyssq + xdiff * (y - mean);
  91.     END;
  92. END;
  93.  
  94.  
  95. PROCEDURE initHistogram (VAR hist: histtype;name:str15);
  96.     {(   var    hist : histtype   );}
  97. VAR
  98.     I: integer;
  99. BEGIN
  100.  
  101.     WITH hist DO
  102.     BEGIN
  103.         min := +INF;
  104.         max := -Inf;
  105.         BinWidth := Inf;
  106.         count := 0;
  107.         maxbincount := 1;{should be 1 to allow scaling for empty histogram}
  108.         FOR I := 0 TO maxclass DO
  109.         cnt[I] := 0;
  110.         id:=name;
  111.     END;
  112. END;
  113.  
  114. FUNCTION histogramcell(val: extended; VAR hist: histtype):integer;
  115. VAR tempcell:integer;templim,delta:extended;
  116. BEGIN
  117.     WITH hist DO
  118.     BEGIN
  119.         IF val>max THEN histogramcell:=maxint
  120.         ELSE IF val<=min THEN histogramcell:=-1
  121.         ELSE BEGIN
  122.          {$IFC PARANOIA} IF binwidth<=0 THEN debugstr('bin widht <=0'); {$ENDC}
  123.         {$IFC PARANOIA} IF binwidth=Inf THEN debugstr('bin widht Inf'); {$ENDC}
  124.             tempcell:=trunc((val-min)/binwidth);
  125.             templim:=min+tempcell*binwidth;        {left boundary of this cell}
  126.             delta:=val-min+tempcell*binwidth;    {?? sometimes val<templim}
  127.             IF val<=templim THEN 
  128.             tempcell:=tempcell-1 {we checked for min, so tempcell>0}
  129.             ELSE
  130.             BEGIN
  131.                 templim:=templim+binwidth;
  132.                 IF val>templim THEN Debugstr('larger')
  133.             END;
  134.       {$IFC PARANOIA} IF tempcell<0 THEN debugstr('tempcell negative'); {$ENDC}
  135.  
  136.             histogramcell:=tempcell;
  137.         END;
  138.     END;{with}
  139. END;
  140.  
  141. PROCEDURE addhist (val: extended; VAR hist: histtype);
  142.  
  143. PROCEDURE secondvalue (val: extended);
  144. VAR
  145.     countmax, countmin: longint;
  146.     slop,valmin, valmax: extended;
  147.     cell: integer;
  148. BEGIN {second value}
  149.     WITH hist DO
  150.     BEGIN
  151.         IF val > max THEN
  152.         BEGIN
  153.             min := max;
  154.             countmin := count - 1;    {we already incremented count for val}
  155.             max := val;
  156.             countmax := 1;
  157.         END
  158.         ELSE
  159.         BEGIN
  160.             countmax := count - 1;
  161.             min := val;
  162.             countmin := 1;
  163.         END;
  164.  
  165.         {min and max are defined & correct}
  166.         valmin := min;                {temporary - copy from misused histogram entries}
  167.         valmax := max;
  168.  
  169.         {find initial scale. try with quarter range slop}
  170.         slop:=(max - min) / 4;
  171.         min := valmin - slop;
  172.         IF (min < 0) & (valmin >0) THEN min := 0;    {fix on zero}
  173.         max := valmax + slop ;
  174.         IF (max > 0) & (valmax < 0) THEN max := 0;    {fix on zero}
  175.  
  176.         {$IFC PARANOIA} IF min>max THEN debugstr('bad max/min'); {$ENDC}
  177.  
  178.         binwidth := (max - min) / (maxClass + 1);
  179.  
  180.         {scales are set up. Now store everything to correct cell}
  181.         cell := histogramcell(valmin,hist);
  182.         cnt[cell] := countmin;
  183.         IF countmin > maxbincount THEN
  184.         maxbincount := countmin;
  185.  
  186.         cell := histogramcell(valmax,hist);
  187.         cnt[cell] := countmax;
  188.         IF countmax > maxbincount THEN
  189.         maxbincount := countmax;
  190.  
  191.     END;
  192. END;{second value}
  193.  
  194. PROCEDURE movebins(frombin,tobin,nrbins:integer);
  195.     {shift bins, and adjust limits. should work in both directions.
  196.     All bins outside the moved range are considered invalid and
  197.     the bin counts will be set to zero. On the Macintosh, we could
  198.     use CMove to speed up. For portability, we use a loop.}
  199. VAR bin,delta:integer;
  200. BEGIN
  201.     IF nrbins<=0 THEN
  202.     {error. should not occur. NOOP for now}
  203.     ELSE WITH hist DO BEGIN
  204.         delta:=tobin-frombin;
  205.         IF frombin<tobin THEN {shift right. delta >0}
  206.         BEGIN
  207.             FOR bin:=frombin+nrbins-1 DOWNTO frombin DO        
  208.             cnt[bin+delta]:=cnt[bin];
  209.         END ELSE IF frombin>tobin THEN {shift left. delta <0}
  210.         BEGIN
  211.             FOR bin:=frombin TO frombin+nrbins-1 DO    
  212.             cnt[bin+delta]:=cnt[bin];
  213.         END;
  214.         max:=max-delta*binwidth;
  215.         min:=min-delta*binwidth;
  216.         {set remaining bin counts to zero}
  217.         FOR bin:=0 TO tobin-1 DO cnt[bin]:=0;
  218.         FOR bin:=tobin+nrbins TO maxclass DO cnt[bin]:=0;
  219.     END;
  220. END;
  221.  
  222. PROCEDURE newcell (val: extended);
  223. VAR
  224.     cell, fromclass,toclass: integer;
  225.     usedcell,delta: integer;
  226.     {val not in range min<val≤max}
  227. BEGIN
  228.     WITH hist DO
  229.     BEGIN
  230.         IF val<= min THEN
  231.         BEGIN
  232.             {left needed. try a shift first}
  233.             usedcell:=maxclass;
  234.             WHILE cnt[usedcell]=0 DO usedcell:=usedcell-1;
  235.             IF usedcell<maxclass THEN BEGIN    {a free cell at right}
  236.                 delta:=(maxclass-usedcell) DIV 2;
  237.                 IF delta=0 THEN delta:=1;
  238.                 MoveBins(0,delta,usedcell+1);
  239.             END
  240.             ELSE BEGIN{left needed. change scale}
  241.                 fromclass := maxclass;
  242.                 FOR cell := maxclass DOWNTO (maxclass DIV 2) + 1 DO
  243.                 BEGIN
  244.                     cnt[cell] := cnt[fromclass] + cnt[fromclass - 1];
  245.                     fromclass := fromclass - 2;
  246.                     IF cnt[cell] > maxbincount THEN
  247.                     maxbincount := cnt[cell];
  248.                 END;{shift right}
  249.                 FOR cell := (maxclass DIV 2) DOWNTO 0 DO
  250.                 cnt[cell] := 0;
  251.                 binwidth := binwidth * 2;
  252.                 min := min - ((maxclass DIV 2) + 1) * binwidth;
  253.             END {left needed. change scale}
  254.         END
  255.         ELSE
  256.         BEGIN {right needed. try a shift first}
  257.             usedcell:=0;
  258.             WHILE cnt[usedcell]=0 DO usedcell:=usedcell+1;
  259.             IF usedcell> 0 THEN BEGIN    {a free cell at left}
  260.                 delta:=usedcell DIV 2;
  261.                 IF delta=0 THEN delta:=1;
  262.                 movebins(usedcell,usedcell-delta,maxclass-usedcell+1);
  263.             END ELSE
  264.             BEGIN  {right needed. change scale}
  265.                 fromclass := 0;
  266.                 FOR cell := 0 TO (maxclass DIV 2) DO
  267.                 BEGIN
  268.                     cnt[cell] := cnt[fromclass] + cnt[fromclass + 1];
  269.                     fromclass := fromclass + 2;
  270.                     IF cnt[cell] > maxbincount THEN
  271.                     maxbincount := cnt[cell];
  272.                 END;{shift left}
  273.                 FOR cell := (maxclass DIV 2) + 1 TO maxclass DO
  274.                 cnt[cell] := 0;
  275.                 binwidth := binwidth * 2;
  276.                 {change scale}
  277.                 max := min + binwidth * (maxclass + 1);
  278.             END; {right needed. change scale}
  279.         END; {right needed.}
  280.     END;{with hist}
  281. END;
  282.  
  283. (* main part procedure addHist *)
  284. VAR
  285.     cell: integer;
  286.     countmin, countmax: longint;
  287. BEGIN
  288.     WITH hist DO
  289.     BEGIN
  290.         count := count + 1;
  291.  
  292.         IF binwidth < Inf THEN    {ordinary case: binwidth defined}
  293.         BEGIN
  294.             WHILE (val <= min) OR (val > max) DO newcell(val);
  295.             cell := histogramcell(val,hist);
  296. {$IFC paranoia} IF (cell<0) OR (cell>maxclass) THEN debugstr('bad histogramcell'); {$ENDC}
  297.             cnt[cell] := cnt[cell] + 1;
  298.             IF cnt[cell] > maxbincount THEN
  299.             maxbincount := cnt[cell];
  300.         END    {ordinary case: binwidth defined}
  301.         ELSE
  302.         BEGIN {exception case: binwidth undefined}
  303.        IF val = max THEN {tie on first value: noop (we already increased count}
  304.             ELSE
  305.             BEGIN
  306.                 IF max = -inf THEN {first observation}
  307.                 max := val
  308.                 ELSE
  309.                 secondValue(val);
  310.             END;
  311.         END;
  312.     END;{with hist}
  313. END; (* addhist *)
  314.  
  315.